<?php

namespace app\model;


use support\Model;

class BaseModel extends Model
{
    /**
     * @var string
     */
    protected $connection = 'mysql';

    /**
     * 格式化日期
     *
     * @param DateTimeInterface $date
     * @return string
     */
    protected function serializeDate(\DateTimeInterface $date)
    {
        return $date->format('Y-m-d H:i:s');
    }

    /**
     * 分页数据
     * @param $query
     * @param int $page
     * @param int $pageSize
     * @param boolean $group
     * @return array
     */
    public function buildPage(&$query, $page=1, $pageSize=15, $group=false)
    {
        if($group){
            $totalCount = $this->setTable(DB::raw("({$query->toSql()}) a"))->mergeBindings($query->getQuery())->count();
//            $totalCountData = $query->selectRaw('count(*) aggregate')->pluck('aggregate')->toArray();
//            $totalCount = count($totalCountData);
        }else{
            $totalCount = $query->count();
        }

        $inputPageNo = request()->input('page');
        $inputPageSize = request()->input('limit');
        if( $inputPageNo ){
            $page = (int)$inputPageNo;
        }
        if( $inputPageSize ){
            $pageSize = (int)$inputPageSize;
        }
        if($page<1){$page=1;}

        if($pageSize<1){$pageSize=15;}

        $data = [];
        $data['pageSize'] = $pageSize;
        $data['totalCount'] = $totalCount;
        $data['totalPage']= ceil($totalCount / $pageSize);
        $data['totalPage'] = $data['totalPage']>0 ? $data['totalPage'] : 1;

        if($data['totalPage']<$page){
            $data['pageNo'] = $page;
        }else{
            $data['pageNo'] = $page;
        }

        $offset = ($data['pageNo']-1)*$data['pageSize'];

        $query = $query->offset($offset)->limit($data['pageSize']);

        return $data;
    }

    /**
     * 跟数据列表对应id获取关系表数据---多对一模式
     * @param $data
     * @param $keyIdField
     * @param $table
     * @param array $constant
     * @return array
     * @throws \think\Exception
     */
    public function getListDataById($data,$keyIdField,$table,$constant=[])
    {
        if(empty($data)){
            return $data;
        }

        $ids = array_column($data, $keyIdField);
        $ids && $ids =  array_unique($ids);

        $idField = isset($constant['idField']) ? $constant['idField'] : 'id';
        $field = isset($constant['field']) ? $constant['field'] : '*';
        if($field!='*'){
            if(is_string($field)){
                $field = explode(',', $field);
            }
            array_unshift($field,$idField);
            $field = array_unique($field);
        }

        $connection = isset($constant['connection']) ? $constant['connection'] : '';

        $listData = DB::connection($connection)->table($table)->select($field)->whereIn($idField,$ids)->get();

        if($listData){
            return array_column(self::convertArray($listData),null,$idField);
        }

        return [];
    }

    /**
     * 跟数据列表对应id获取关系表数据---一对多模式
     * @param $data
     * @param $keyIdField
     * @param $table
     * @param array $constant [idField,field,connection,order]
     * @return array
     * @throws \think\Exception
     */
    public function getListAllDataById($data,$keyIdField,$table,$constant=[])
    {
        if(empty($data)){
            return $data;
        }

        $ids = array_column($data, $keyIdField);
        $ids && $ids =  array_unique($ids);

        $idField = isset($constant['idField']) ? $constant['idField'] : 'id';
        $field = isset($constant['field']) ? $constant['field'] : '*';
        if($field!='*'){
            if(is_string($field)){
                $field = explode(',', $field);
            }
            array_unshift($field,$idField);
            $field = array_unique($field);
        }

        $connection = isset($constant['connection']) ? $constant['connection'] : '';
        $order = isset($constant['order']) ? explode(' ',$constant['order']) : [$idField,'ASC'];
        $listData =  DB::connection($connection)->table($table)->select($field)->whereIn($idField,$ids)->orderBy($order[0],$order[1])->get();

        $listData = self::convertArray($listData);
        $returnData = [];
        if($listData){
            foreach ($listData as $val){
                $returnData[$val[$idField]][] = $val;
            }

        }

        return $returnData;
    }

    /**
     * 跟数据对应id获取关系表数据,获取详情数据
     * @param $data
     * @param $keyIdField
     * @param $table
     * @param array $constant
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function getDetailDataById($data,$keyIdField,$table,$constant=[])
    {
        if(empty($data)){
            return $data;
        }

        $id = $data[$keyIdField];

        $idField = isset($constant['idField']) ? $constant['idField'] : 'id';
        $field = isset($constant['field']) ? $constant['field'] : '*';
        if($field!='*'){
            if(is_string($field)){
                $field = explode(',', $field);
            }
            array_unshift($field,$idField);
            $field = array_unique($field);
        }

        $connection = isset($constant['connection']) ? $constant['connection'] : '';
        $detailData =  DB::connection($connection)->table($table)->select($field)->where($idField,$id)->first();

        if($detailData){
            return self::convertArray($detailData);
        }

        return [];
    }

    /**
     * 填充公共字段值，方便添加更新
     * @param array $data
     * @param boolean $isAdd
     * @return array
     */
    public function fillCommonField($data=[], $isAdd=true)
    {
        if($isAdd){
            $data['adduser'] = isset($data['adduser']) ? $data['adduser']:(int) request()->curUserId;
            $data['createtime'] = isset($data['createtime']) ? $data['createtime'] : date('Y-m-d H:i:s');
            $data['updatetime'] = date('Y-m-d H:i:s');
        }else{
            $data['updateuser'] = isset($data['updateuser']) ? $data['updateuser']:(int) request()->curUserId;

            $data['updatetime'] = date('Y-m-d H:i:s');
        }
        return $data;
    }

    public static function convertArray($data)
    {
        return (array) json_decode(json_encode($data), true);
    }

    /**
     * 线形和柱形图报表数据格式组装
     * @param $data
     * @param $targetFields
     * @param $xField
     * @param $types
     * @param $tooltips
     * @return array
     */
    public function assembleLineData($data,$targetFields,$xField,$types=[],$tooltips=[])
    {
        $returnData = [
            'categories'=>[],
            'series'=>[],
        ];
        foreach ($data as $k=>$val){
            $returnData['categories'][$k] = $val[$xField];
            $index = 0;
            foreach ($targetFields as $key=>$field){
                $returnData['series'][$key]['name']=$field;
                $returnData['series'][$key]['type']= isset($types[$key]) ? $types[$key] : 'bar';
                $returnData['series'][$key]['data'][$k] = $val[$key];
                $returnData['series'][$key]['yAxisIndex']= $index;
                $index++;
            }
        }
        $returnData['series'] = array_values($returnData['series']);
        return $returnData;
    }

    /**
     * 获取距离当前时间天数的键或者标识
     * @param $dateTime
     * @return string
     */
    public function computDayKey($dateTime)
    {
        $diffTime = time() - strtotime($dateTime);
        $days = floor($diffTime/86400);

        if($days<=30){
            return 'thirty_days';
        }elseif($days>30 && $days<=60){
            return 'thirty_sixty_days';
        }elseif($days>60 && $days<=90){
            return 'sixty_ninety_days';
        }elseif($days>90 && $days<=180){
            return 'ninety_eightys_days';
        }else{
            //180天以上
            return 'eightys_days';
        }
    }

    public function getWhere($where)
    {
        $query = $this;

        foreach ($where as $key=>$val){
            if(!is_array($val)){
                $query = $query->where($key,$val);
            }elseif(isset($val['or'])){
                $query = $query->Where(function ($query) use($val){
                    foreach($val['or'] as $v){
                        $query = $query->orWhere(function ($query) use ($v){
                            foreach($v as $kk=>$vv){
                                if(is_array($vv)){
                                    $query = $this->customeWhere($query, $vv);
                                }else{
                                    $query = $query->where($vv);
                                }
                            }
                            return $query;
                        });
                    }

                });
            }else{
                $query = $this->customeWhere($query, $val);
            }
        }

        return $query;
    }

    protected function customeWhere($query, $val)
    {
        switch ($val[1]){
            case 'in':
                $query = $query->whereIn($val[0],$val[2]);
                break;
            case 'notin':
                $query = $query->whereNotIn($val[0],$val[2]);
                break;
            case 'between':
                $query = $query->whereBetween($val[0],$val[2]);
                break;
            case 'notbetween':
                $query = $query->whereNotBetween($val[0],$val[2]);
                break;
            case 'null':
                $query = $query->whereNull($val[0]);
                break;
            case 'notnull':
                $query = $query->whereNotNull($val[0]);
                break;
            case 'custom':
                $query = $query->whereRaw($val[0]);
                break;
            default:
                $query = $query->where([$val]);
        }

        return $query;
    }

    public function getSelect($query,$fields)
    {
        $fieldData = [];
        $raw = false;
        foreach ($fields as $key=>$val){
            if(is_numeric($key)){
                $fieldData[] = $val;
            }else{
                $query->selectRaw($val.' '.$key);
                $raw = true;
            }
        }

        $fieldData && $raw==true && $query->addSelect($fieldData);
        $fieldData && $raw==false && $query->select($fieldData);

        return $query;
    }

    protected function unsetCommonFields($data,$extFields=[])
    {
        $commfields = ['createtime','updatetime','adduser','isdel','status'];
        $unsetFields = array_merge($commfields,$extFields);
        if(isset($data[0]) && !empty($data)){
            foreach ($data as $val){
                foreach($unsetFields as $key){
                    if(isset($val[$key])){
                        unset($val[$key]);
                    }
                }
            }
        }else{
            foreach($unsetFields as $key){
                if(isset($data[$key])){
                    unset($data[$key]);
                }
            }
        }

        return $data;
    }

    public function index($where, $field = [], $order = [])
    {
        $query = $this->getWhere($where);

        $field && $query->select($field);

        $data = $this->buildPage($query);
        $order && is_array($order) && $query->orderBy($order[0],$order[1]);
        $order && is_string($order) && $query->orderByRaw($order);
        $order==false && $query->orderBy($this->primaryKey,'desc');

        $data['data'] = $query->get();

        return $data;
    }
}
